package player.bum.vn.common;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class UrlParse {
	public static Map<String, String[]> parseUrlQueryString(String str) {
		final String s = str;
		if (s == null) {
			return new HashMap<String, String[]>(0);
		}

		HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
		int pos = 0, end = s.length();

		while (pos < end) {
			int nameStart = pos;
			int nameEnd = -1;
			int valueStart = -1;
			int valueEnd = -1;

			boolean parsingName = true;
			boolean decodeName = false;
			boolean decodeValue = false;
			boolean parameterComplete = false;

			do {
				switch (s.charAt(pos)) {
					case '=':
						if (parsingName) {
							// Name finished. Value starts from next character
							nameEnd = pos;
							parsingName = false;
							valueStart = ++pos;
						} else {
							// Equals character in value
							pos++;
						}
						break;
					case '&':
						if (parsingName) {
							// Name finished. No value.
							nameEnd = pos;
						} else {
							// Value finished
							valueEnd = pos;
						}
						parameterComplete = true;
						pos++;
						break;
					case '%':
//				case '+':
						// Decoding required
						if (parsingName) {
							decodeName = true;
						} else {
							decodeValue = true;
						}
						pos++;
						break;
					default:
						pos++;
						break;
				}
			} while (!parameterComplete && pos < end);

			if (pos == end) {
				if (nameEnd == -1) {
					nameEnd = pos;
				} else if (valueStart > -1 && valueEnd == -1) {
					valueEnd = pos;
				}
			}

			String name = null;
			String value = null;

			if (nameEnd > nameStart) {
				name = s.substring(nameStart, nameEnd);
				if (decodeName) {
					name = urlDecode(name);
				}
			}

			if (valueEnd > valueStart) {
				value = s.substring(valueStart, valueEnd);
				if (decodeValue) {
					value = urlDecode(value);
				}
			}

			addParameter(map, name, value);
		}

		return toValueArray(map);
	}

	/*-------- Internal Method Region --------*/

	private static String urlDecode(String s) {
		try {
			return URLDecoder.decode(s, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Error in urlDecode.", e);
		}
	}

	private static void addParameter(Map<String, ArrayList<String>> map, String key, String value) {
		if (key == null) {
			return;
		}
		if (value == null) {
			value = "";
		}
		
		ArrayList<String> values = map.get(key);
		if (values == null) {
			values = new ArrayList<String>(1);
			map.put(key, values);
		}
		values.add(value);
	}

	private static HashMap<String, String[]> toValueArray(Map<String, ArrayList<String>> map) {
		HashMap<String, String[]> result = new HashMap<String, String[]>(map.size());

		for (Map.Entry<String, ArrayList<String>> e : map.entrySet()) {
			result.put(e.getKey(), e.getValue().toArray(new String[0]));
		}

		return result;
	}
}
